<?php


namespace App\Services;

use App\Models\BidGoods;
use App\Models\Goods;
use App\Models\GoodsFile;
use App\Models\Bid;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Tymon\JWTAuth\Contracts\JWTSubject;
use App\Utils\Code;

class GoodsService extends BaseService
{

    /**
     * 创建
     * @param array $params
     * @return Builder|\Illuminate\Database\Eloquent\Model|object|JWTSubject|null
     * @throws \Exception
     */
    public function store(array $params) {
        if (!$this->checkParams($params)){
            throw new \Exception('请求参数验证不通过', Code::PARAMETER_ERROR);
        }
        if (Goods::where('goods_code', $params['goods_code'])->whereNull('deleted_at')->exists()) {
            throw new \Exception('该商品编号已经被使用', Code::EXIST_REPEAT);
        }
        $userId = isset($params['user_id']) ? $params['user_id'] : \Auth::id();
        return \DB::transaction(function () use ($params, $userId) {
            $model = new Goods();
            $model->user_id = $userId;
            $model->goods_code = $params['goods_code'];
            if (isset($params['goods_name']) && $params['goods_name']) {
                $model->goods_name = $params['goods_name'];
            }
            if (isset($params['label_price']) && $params['label_price']) {
                $model->label_price = (double)$params['label_price'];
            }
            if (isset($params['cost_price']) && $params['cost_price']) {
                $model->cost_price = (double)$params['cost_price'];
            }
            if (isset($params['supplier_id']) && $params['supplier_id']) {
                $model->supplier_id = (int)$params['supplier_id'];
            }
            if (isset($params['stock']) && $params['stock']) {
                $model->stock = (int)$params['stock'];
            }
            if (isset($params['seat']) && $params['seat']) {
                $model->seat = $params['seat'];
            }
            if (isset($params['weight']) && $params['weight']) {
                $model->weight = $params['weight'];
            }
            if (isset($params['description']) && $params['description']) {
                $model->description = $params['description'];
            }
            if (isset($params['remarks']) && $params['remarks']) {
                $model->remarks = $params['remarks'];
            }
            if (key_exists('is_bid', $params)) {
                $model->is_bid = (int)$params['is_bid'];
            }
            if (key_exists('is_show', $params)) {
                $model->is_show = (int)$params['is_show'];
            }
            if (key_exists('is_onshelf', $params)) {
                $model->is_onshelf = (int)$params['is_onshelf'];
            }
            if (isset($params['released_at']) && $params['released_at']) {
                $model->released_at = $params['released_at'];
            } else {
                $model->released_at = date('Y-m-d H:i:s');
            }
            $model->save();
            // 商品文件
            $files = [];
            if (isset($params['videos']) && $params['videos']) {
                foreach ($params['videos'] as $video) {
                    $files[] = new GoodsFile([
                        'type' => 1,
                        'path' => $video
                    ]);
                }
            }
            if (isset($params['images']) && $params['images']) {
                foreach ($params['images'] as $image) {
                    $files[] = new GoodsFile([
                        'type' => 2,
                        'path' => $image
                    ]);
                }
            }
            if ($files) {
                $model->files()->saveMany($files);
            }

            return $this->show([ 'goods_id' => $model->goods_id ]);
        });
    }

    /**
     * 验证参数
     * @param array $params
     * @param null $id
     * @param bool $isUpdate
     * @return array
     * @throws \Exception
     */
    private function checkParams(array $params, $isUpdate = false){
        $rules = [
            'goods_code' => ['bail', 'required'],
            'label_price' => ['bail', 'required', 'numeric'],
            'goods_name' => ['bail', 'nullable', 'string'],
            'cost_price' => ['bail', 'nullable', 'numeric'],
            'stock' => ['bail', 'nullable', 'integer'],
            'seat' => ['bail', 'nullable'],
            'description' => ['bail', 'nullable', 'string'],
            'supplier_id' => ['bail', 'nullable', 'integer'],
            'weight' => ['bail', 'nullable', 'numeric'],
            'remarks' => ['bail', 'nullable', 'string'],
            'is_bid' => ['bail', 'integer', 'in:0,1'],
            'is_show' => ['bail', 'integer', 'in:0,1'],
            'is_onshelf' => ['bail', 'integer', 'in:0,1'],
            'released_at' => ['bail', 'nullable', 'date']
        ];
        if ($isUpdate){
            // 删除必选条件
            foreach ($rules as $field => &$rule){
                if (isset($rule[1]) && $rule[1] == 'required') {
                    $rule[1] = 'nullable';
                }
            }
        }
        $validator = Validator::make($params, $rules, [], [
            'goods_code' => '商品编号',
            'label_price' => '起拍价',
            'goods_name' => '商品名称',
            'cost_price' => '成本价',
            'stock' => '片数',
            'seat' => '位置',
            'description' => '商品介绍',
            'supplier_id' => '货主',
            'weight' => '重量',
            'remarks' => '备注',
            'is_bid' => '投标状态',
            'is_show' => '展示状态',
            'is_onshelf' => '上架状态',
            'released_at' => '上架时间',
        ]);
        if ($validator->fails()) {
            throw new \Exception($validator->errors()->first(), Code::PARAMETER_ERROR);
        }
        return $params;
    }

    /**
     * 删除
     * @param $id
     * @return Builder|\Illuminate\Database\Eloquent\Model|object|JWTSubject|null
     * @throws \Exception
     */
    public function destroy($id = null) {
        if (!$id) {
            throw new \Exception('商品主键不能为空', Code::PARAMETER_ERROR);
        }
        if (BidGoods::where('goods_id', $id)->exists()) {
            throw new \Exception('该商品已被投标，无法删除', Code::PARAMETER_ERROR);
        }
        Goods::where('goods_id', $id)->delete();
        return true;
    }

    /**
     * 修改
     * @param array $params
     * @param $id
     * @return Builder|\Illuminate\Database\Eloquent\Model|object|JWTSubject|null
     * @throws \Exception
     */
    public function update(array $params, $id = null) {
        if (!$this->checkParams($params, true)){
            throw new \Exception('请求参数验证不通过', Code::PARAMETER_ERROR);
        }
        return \DB::transaction(function () use ($params, $id) {
            if (!$model = Goods::where('goods_id', $id)->whereNull('deleted_at')->first()) {
                throw new \Exception('该商品不存在或已被删除', Code::EXIST_REPEAT);
            }
            if (isset($params['goods_code']) && $params['goods_code']) {
                $model->goods_code = $params['goods_code'];
            }
            if (isset($params['label_price']) && $params['label_price']) {
                $model->label_price = (double)$params['label_price'];
            }
            if (isset($params['released_at']) && $params['released_at']) {
                $model->released_at = $params['released_at'];
            }
            if (key_exists('goods_name', $params)) {
                $model->goods_name = $params['goods_name'];
            }
            if (key_exists('cost_price', $params)) {
                $model->cost_price = (double)$params['cost_price'];
            }
            if (key_exists('supplier_id', $params)) {
                $model->supplier_id = (int)$params['supplier_id'];
            }
            if (key_exists('stock', $params)) {
                $model->stock = (int)$params['stock'];
            }
            if (key_exists('seat', $params)) {
                $model->seat = $params['seat'];
            }
            if (key_exists('weight', $params)) {
                $model->weight = $params['weight'];
            }
            if (key_exists('description', $params)) {
                $model->description = $params['description'];
            }
            if (key_exists('remarks', $params)) {
                $model->remarks = $params['remarks'];
            }
            if (key_exists('is_bid', $params)) {
                $model->is_bid = (int)$params['is_bid'];
            }
            if (key_exists('is_show', $params)) {
                $model->is_show = (int)$params['is_show'];
            }
            if (key_exists('is_onshelf', $params)) {
                $model->is_onshelf = (int)$params['is_onshelf'];
                if ($model->is_onshelf == 0) {
                    $model->is_show = 0;
                    $model->is_bid = 0;
                }
            }
            $model->save();
            // 商品文件
            $files = [];
            if (isset($params['videos'])) {
                if ($params['videos'] && is_array($params['videos'])) {
                    foreach ($params['videos'] as $video) {
                        $files[] = new GoodsFile([
                            'type' => 1,
                            'path' => $video
                        ]);
                    }
                    $model->files()->where('type', 1)->delete();
                    $model->files()->saveMany($files);
                    $files = [];
                } else {
                    $model->files()->where('type', 1)->delete();
                }
            }
            if (isset($params['images'])) {
                if ($params['images'] && is_array($params['images'])) {
                    foreach ($params['images'] as $image) {
                        $files[] = new GoodsFile([
                            'type' => 2,
                            'path' => $image
                        ]);
                    }
                    $model->files()->where('type', 2)->delete();
                    $model->files()->saveMany($files);
                    $files = [];
                } else {
                    $model->files()->where('type', 2)->delete();
                }
            }

            return $this->show([ 'goods_id' => $model->goods_id ]);
        });
    }

    /**
     * 查看详情
     * @param $id
     * @return Builder|\Illuminate\Database\Eloquent\Model|object|JWTSubject|null
     * @throws \Exception
     */
    public function show(array $params) {
        if (isset($params['goods_id']) && $params['goods_id']) {
            $model = Goods::where('goods_id', (int)$params['goods_id']);

        } elseif (isset($params['goods_code']) && $params['goods_code']) {
            $model = Goods::where('goods_code', $params['goods_code']);
        } else {
            throw new \Exception('缺少标品id或标号', Code::PARAMETER_ERROR);
        }
        $model = $model->with([
                'supplier',
                'bidGoods',
                'cover',
                'images'
            ])
            ->whereNull('deleted_at')->first();
        if (!$model) {
            throw new \Exception('该标品不存在或已被删除', Code::EXIST_REPEAT);
        }
        return $model;
    }

    /**
     * 查看列表
     * @param array $params
     * @return Builder|\Illuminate\Database\Eloquent\Model|object|JWTSubject|null
     * @throws \Exception
     */
    public function index(array $params) {
        if (isset($params['is_biding']) && $params['is_biding'] == 1) {
            if (\DB::table('user_extra')->where('user_id', \Auth::id())->value('can_bid') == 0) {
                throw new \Exception('您目前没有投标权限，请先联系管理员获取投标权限', Code::PARAMETER_ERROR);
            }
            $bid = Bid::where('status', 1)->whereNull('deleted_at')->first();
            if (!$bid) {
                throw new \Exception('暂无进行中的投标', Code::PARAMETER_ERROR);
            }
        }
        $model = $this->handleSearch($params);
        if (isset($params['is_export']) && $params['is_export'] == 1) {
            return $model->orderBy('goods_code', 'asc')->orderBy('goods_id', 'desc')->get();
        } else {
            return $model->orderBy('goods_code', 'asc')->orderBy('goods_id', 'desc')
                ->paginate(isset($params['per_page']) ? (int)$params['per_page'] : null);
        }
    }

    public function handleSearch(array $params = []) {
        $model = Goods::with(['supplier', 'cover'])->whereNull('deleted_at');
        if (isset($params['goods_ids']) && is_array($params['goods_ids'])) {
            $model = $model->whereIn('goods_id', $params['goods_ids']);
            return $model;
        }
        if (isset($params['goods_code']) && $params['goods_code']) {
            $model = $model->where('goods_code', $params['goods_code']);
        }
        if (isset($params['seat']) && $params['seat']) {
            $model = $model->where('seat', $params['seat']);
        }
        if (isset($params['supplier_id']) && $params['supplier_id']) {
            $model = $model->where('supplier_id', $params['supplier_id']);
        }
        if (isset($params['goods_name']) && $params['goods_name']) {
            $model = $model->where('goods_name', 'like', '%'.$params['goods_name'].'%');
        }
        if (isset($params['description']) && $params['description']) {
            $model = $model->where('description', 'like', '%'.$params['description'].'%');
        }
        if (isset($params['remarks']) && $params['remarks']) {
            $model = $model->where('remarks', 'like', '%'.$params['remarks'].'%');
        }
        if (isset($params['is_bid'])) {
            $model = $model->where('is_bid', (int)$params['is_bid']);
        }
        if (isset($params['is_onshelf'])) {
            $model = $model->where('is_onshelf', (int)$params['is_onshelf']);
        }
        if (isset($params['is_show'])) {
            $model = $model->where('is_show', (int)$params['is_show']);
        }
        if (isset($params['released_at']) && $params['released_at'] && is_array($params['released_at'])) {
            if (isset($params['released_at'][0]) && $params['released_at'][0]) {
                $model = $model->where('released_at', '>=', $params['released_at'][0]);
            }
            if (isset($params['released_at'][1]) && $params['released_at'][1]) {
                $model = $model->where('released_at', '<=', $params['released_at'][1]);
            }
        }
        return $model;
    }

      /**
     * 打印列表
     * @param array $params
     * @return Builder|\Illuminate\Database\Eloquent\Model|object|JWTSubject|null
     * @throws \Exception
     */
    public function print(array $params) {
        $model = $this->handleSearch($params);
        $lists = $model->get()->toArray();
        $data = [
            'lists' => [],
            'supplier_name' => '',
            'supplier_phone' => '',
            'current_time' => date('Y-m-d H:i:s'),
            'goods_count' => count($lists),
            'goods_total' => 0,
            'cost_price' => 0
        ];
        foreach ($lists as &$list) {
            $list['supplier_name'] = isset($list['supplier']['name']) ? $list['supplier']['name'] : '';
            if (!empty($list['supplier']['name'])) {
                $data['supplier_name'] = $list['supplier']['name'];
            }
            if (!empty($list['supplier']['phone'])) {
                $data['supplier_phone'] = $list['supplier']['phone'];
            }
        }
        $data['lists'] = $lists;
        return $data;
    }

    /**
     * 导出列表
     * @param array $params
     * @return Builder|\Illuminate\Database\Eloquent\Model|object|JWTSubject|null
     * @throws \Exception
     */
    public function export(array $params) {
        $model = $this->handleSearch($params);
        $lists = $model->get()->toArray();
        foreach ($lists as &$list) {
            $list['supplier_name'] = isset($list['supplier']['name']) ? $list['supplier']['name'] : '';
        }
        return $lists;
    }

    /**
     * 打印标签
     * @param array $params
     * @return Builder|\Illuminate\Database\Eloquent\Model|object|JWTSubject|null
     * @throws \Exception
     */
    public function printLabel(array $params) {
        $model = $this->handleSearch($params);
        $lists = $model->get()->toArray();
        foreach ($lists as &$list) {
            $list['supplier_name'] = isset($list['supplier']['name']) ? $list['supplier']['name'] : '';
        }
        return $lists;
    }

    /**
     * 批量修改
     * @param array $params
     * @return Builder|\Illuminate\Database\Eloquent\Model|object|JWTSubject|null
     * @throws \Exception
     */
    public function updateAll(array $params) {
        if (!$goods_ids = isset($params['goods_ids']) ? $params['goods_ids'] : null) {
            throw new \Exception('商品主键不能为空', Code::PARAMETER_ERROR);
        }
        $goods_ids = is_array($goods_ids) ? $goods_ids : [$goods_ids];
        $data = [];
        if (isset($params['label_price']) && $params['label_price']) {
            $data['label_price'] = (double)$params['label_price'];
        }
        if (isset($params['released_at']) && $params['released_at']) {
            $data['released_at'] = $params['released_at'];
        }
        if (isset($params['goods_name']) && $params['goods_name']) {
            $data['goods_name'] = $params['goods_name'];
        }
        if (isset($params['cost_price']) && $params['cost_price']) {
            $data['cost_price'] = (double)$params['cost_price'];
        }
        if (isset($params['supplier_id']) && $params['supplier_id']) {
            $data['supplier_id'] = (int)$params['supplier_id'];
        }
        if (isset($params['stock']) && $params['stock']) {
            $data['stock'] = (int)$params['stock'];
        }
        if (isset($params['weight']) && $params['weight']) {
            $data['weight'] = $params['weight'];
        }
        if (isset($params['description']) && $params['description']) {
            $data['description'] = $params['description'];
        }
        if (isset($params['remarks']) && $params['remarks']) {
            $data['remarks'] = $params['remarks'];
        }
        if (isset($params['is_bid']) && in_array((int)$params['is_bid'], [0, 1])) {
            $data['is_bid'] = (int)$params['is_bid'];
        }
        if (isset($params['is_show']) && in_array((int)$params['is_show'], [0, 1])) {
            $data['is_show'] = (int)$params['is_show'];
        }
        if (isset($params['is_onshelf']) && in_array((int)$params['is_onshelf'], [0, 1])) {
            $data['is_onshelf'] = (int)$params['is_onshelf'];
        }
        if (!$data) {
            throw new \Exception('请填写你要更新的内容', Code::PARAMETER_ERROR);
        }
        \DB::table('goods')->whereIn('goods_id', $goods_ids)->update($data);
        return true;
    }

    /**
     * 批量删除
     * @param array $params
     * @return Builder|\Illuminate\Database\Eloquent\Model|object|JWTSubject|null
     * @throws \Exception
     */
    public function destroyAll(array $params) {
        if (!$goods_ids = isset($params['goods_ids']) ? $params['goods_ids'] : null) {
            throw new \Exception('商品主键不能为空', Code::PARAMETER_ERROR);
        }
        $goods_ids = is_array($goods_ids) ? $goods_ids : [$goods_ids];
        if (BidGoods::whereIn('goods_id', $goods_ids)->exists()) {
            throw new \Exception('存在已被投标的商品，无法删除', Code::PARAMETER_ERROR);
        }
        return Goods::whereIn('goods_id', $goods_ids)->delete();
    }
}
